package cn.com.anysdk.oss.impl;

import cn.com.anysdk.core.util.StringUtils;
import cn.com.anysdk.oss.api.IOssService;
import cn.com.anysdk.oss.api.IOssConfig;
import cn.com.anysdk.oss.api.UploadOptions;
import cn.com.anysdk.oss.config.LocalFileSystemConfig;
import cn.com.anysdk.oss.exception.OssException;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;

/**
 * 本地文件系统实现
 * 支持基本的文件操作和访问控制
 */
@Slf4j
public class LocalFileSystemService implements IOssService {
    private final LocalFileSystemConfig config;

    public LocalFileSystemService(IOssConfig config) {
        if (!(config instanceof LocalFileSystemConfig)) {
            throw new IllegalArgumentException("Config must be instance of LocalFileSystemConfig");
        }
        this.config = (LocalFileSystemConfig) config;
    }

    @Override
    public String uploadFile(String objectKey, File file) {
        return uploadFile(objectKey, file, UploadOptions.publicFile());
    }

    @Override
    public String uploadFile(String objectKey, InputStream inputStream, long size) {
        try {
            String uniqueObjectKey = generateUniqueObjectKey(objectKey);
            Path targetPath = getFullPath(uniqueObjectKey);
            Files.createDirectories(targetPath.getParent());
            Files.copy(inputStream, targetPath);
            log.debug("Upload file success, path: {}", uniqueObjectKey);
            return getFileUrl(uniqueObjectKey);
        } catch (IOException e) {
            throw new OssException("Upload file failed: " + e.getMessage(), e);
        }
    }

    @Override
    public String uploadFile(String objectKey, File file, UploadOptions options) {
        try {
            if (StringUtils.isBlank(objectKey)) {
                throw new IllegalArgumentException("Object key cannot be empty");
            }
            if (file == null || !file.exists()) {
                throw new IllegalArgumentException("File does not exist");
            }

            String uniqueObjectKey = generateUniqueObjectKey(objectKey);
            Path targetPath = getFullPath(uniqueObjectKey);
            Files.createDirectories(targetPath.getParent());
            Files.copy(file.toPath(), targetPath);

            log.debug("Upload file success, path: {}", uniqueObjectKey);
            return getFileUrl(uniqueObjectKey, options.isPrivate() ? options.getExpireTime() : null);
        } catch (IOException e) {
            throw new OssException("Upload file failed: " + e.getMessage(), e);
        }
    }

    @Override
    public InputStream downloadFile(String objectKey) {
        try {
            if (StringUtils.isBlank(objectKey)) {
                throw new IllegalArgumentException("Object key cannot be empty");
            }

            Path filePath = getFullPath(objectKey);
            if (!Files.exists(filePath)) {
                throw new FileNotFoundException("File not found: " + objectKey);
            }

            log.debug("Download file success, path: {}", objectKey);
            return new FileInputStream(filePath.toFile());
        } catch (IOException e) {
            throw new OssException("Download file failed: " + e.getMessage(), e);
        }
    }

    @Override
    public void deleteFile(String objectKey) {
        try {
            if (StringUtils.isBlank(objectKey)) {
                throw new IllegalArgumentException("Object key cannot be empty");
            }

            Path filePath = getFullPath(objectKey);
            if (!Files.exists(filePath)) {
                throw new FileNotFoundException("File not found: " + objectKey);
            }

            Files.delete(filePath);
            log.debug("Delete file success, path: {}", objectKey);
        } catch (IOException e) {
            throw new OssException("Delete file failed: " + e.getMessage(), e);
        }
    }

    @Override
    public void deleteFiles(List<String> objectKeys) {
        for (String objectKey : objectKeys) {
            deleteFile(objectKey);
        }
    }

    @Override
    public String getFileUrl(String objectKey) {
        return getFileUrl(objectKey, null);
    }

    @Override
    public String getSignedUrl(String objectKey, long expireSeconds) {
        return getFileUrl(objectKey, expireSeconds);
    }

    @Override
    public boolean doesObjectExist(String objectKey) {
        if (StringUtils.isBlank(objectKey)) {
            return false;
        }
        return Files.exists(getFullPath(objectKey));
    }


    @Override
    public IOssConfig getConfig() {
        return this.config;
    }

    @Override
    public boolean validateConfig() {
        return config != null &&
               config.getEndpoint() != null && !config.getEndpoint().trim().isEmpty();
    }

    private Path getFullPath(String objectKey) {
        return Paths.get(config.getBasePath(), objectKey);
    }

    /**
     * 生成唯一的对象键，避免文件名冲突
     * @param originalObjectKey 原始对象键
     * @return 带UUID前缀的唯一对象键
     */
    private String generateUniqueObjectKey(String originalObjectKey) {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        
        // 如果原始键包含路径分隔符，保持目录结构
        int lastSlashIndex = originalObjectKey.lastIndexOf("/");
        if (lastSlashIndex != -1) {
            String directory = originalObjectKey.substring(0, lastSlashIndex + 1);
            String fileName = originalObjectKey.substring(lastSlashIndex + 1);
            return directory + uuid + "_" + fileName;
        } else {
            return uuid + "_" + originalObjectKey;
        }
    }

    private String getFileUrl(String objectKey, Long expireTime) {
        Path filePath = getFullPath(objectKey);
        if (config.isPrivateMode() || expireTime != null) {
            // 本地文件系统不支持签名URL，返回文件路径
            return filePath.toString();
        } else {
            return String.format("file://%s", filePath);
        }
    }
}